package org.example;

import com.alipay.remoting.exception.CodecException;
import com.alipay.remoting.serialization.SerializerManager;
import io.vertx.core.buffer.Buffer;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;

/**
 * 网关内外沟通用消息体
 */
@Getter
@Setter
@ToString
public class CommonMsg implements Serializable {

    //    包头[ 包体长度 int + 校验和 byte + src short+ dst short
    //    + 消息类型 short + 消息状态 byte + 包编号 long ]
    //    包体[ 数据 byte[] ]

    private int bodyLength;

    private byte checksum;

    private short msgSrc;

    private short msgDst;

    private short msgType;

    private byte status;

    private long msgNo;

    @ToString.Exclude
    private byte[] body;


    ////////////////////////////////
    private boolean isLegal;

    private short errCode;

    private long timestamp;


    public void setBody(byte[] body) {
        this.body = body;
        this.checksum = checksum(this.body);
        System.out.println("set checksum = " + this.checksum);
    }


    public boolean check(byte[] bytes) {
        byte sum = checksum(bytes);
        System.out.println("check sum = " + sum + "  vs " + this.checksum);
        return sum == this.checksum;
    }

    private static byte checksum(byte[] bytes) {
        byte sum = 0;
        for(byte b: bytes){
            sum ^= b;
        }
        return sum;
    }


    public byte[] serialize() throws CodecException {
        return SerializerManager.getSerializer(SerializerManager.Hessian2).serialize(this);
    }

    public static CommonMsg deserialize(byte[] body) throws CodecException {
        return SerializerManager.getSerializer(SerializerManager.Hessian2).deserialize(body,CommonMsg.class.getName());
    }

    public Buffer encodeToBuffer() {
        return Buffer.buffer().appendInt(this.getBodyLength())
                .appendByte(this.getChecksum())
                .appendShort(this.getMsgSrc())
                .appendShort(this.getMsgDst())
                .appendShort(this.getMsgType())
                .appendByte(this.getStatus())
                .appendLong(this.getMsgNo())
                .appendBytes(this.getBody());
    }


    public static CommonMsg decodeFromBufferNoCsCheck(Buffer buffer) {

        int bodyLength = buffer.getInt(0);
        byte checksum = buffer.getByte(4);
        short msgSrc = buffer.getShort(5);
        short msgDst = buffer.getShort(7);
        short msgType = buffer.getShort(9);
        byte status = buffer.getByte(11);
        long packetNo = buffer.getLong(12);
        byte[] bodyBytes = buffer.getBytes(20, 20 + bodyLength);

        CommonMsg msg = new CommonMsg();
        //判断校验和 防止传输错误和篡改
        msg.setBodyLength(bodyBytes.length);
        msg.setChecksum(checksum);
        msg.setMsgSrc(msgSrc);
        msg.setMsgDst(msgDst);
        msg.setMsgType(msgType);
        msg.setStatus(status);
        msg.setBody(bodyBytes);
        msg.setMsgNo(packetNo);

        return msg;

    }
}
